﻿' Copyright (C) 2015 HTTPBuilder
'
' This program is free software: you can redistribute it and/or modify it under the +terms 
' of the GNU General Public License as published by the Free Software Foundation, either 
' version 3 of the License, or (at your option) any later version.

' This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
' without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
' See the GNU General Public License for more details.

' You should have received a copy of the GNU General Public License along with this program.
' If not, see http://www.gnu.org/licenses/. 

Imports System.Collections
Imports System.Collections.Generic

Friend NotInheritable Class HeaderCollection
    Implements IDictionary(Of String, String)

    Private _innerList As Dictionary(Of String, String)

#Region "Constructor"
    Public Sub New()
        _innerList = New Dictionary(Of String, String)
    End Sub

    Public Sub New(content As String)
        Me.New()

        CollectHeaders(content)
    End Sub
#End Region

#Region "Private methods"
    Private Sub CollectHeaders(headerText As String)
        For Each headerLine As String In Split(headerText, vbCr)
            headerLine = headerLine
            Dim headers() As String = Split(headerLine, ":")
            If headers.Count = 2 Then
                Dim key As String = headers(0).Trim
                Dim value As String = headers(1).Trim

                If _innerList.ContainsKey(key.ToLower) Then
                    _innerList.Remove(key.ToLower)
                End If
                _innerList.Add(key.ToLower, value)
            End If
        Next
    End Sub
#End Region


    Public Sub SetHeaders(ByRef request As Net.HttpWebRequest)
        For Each key As String In _innerList.Keys
            Select Case key.ToLower
                Case "content-type"
                    request.ContentType = _innerList("content-type")
                    request.MediaType = _innerList("content-type")
                Case "content-length"
                    request.ContentLength = _innerList("content-length")
                Case "user-agent"
                    request.UserAgent = _innerList("user-agent")
                Case "keep-alive"
                    request.KeepAlive = True
                Case "connection"
                    request.Connection = _innerList("connection")
                Case Else
                    request.Headers(key) = _innerList(key)
            End Select
        Next
    End Sub

    Public Sub Add(item As KeyValuePair(Of String, String)) Implements ICollection(Of KeyValuePair(Of String, String)).Add
        Me.Add(item.Key.ToLower, item.Value)
    End Sub

    Public Sub Clear() Implements ICollection(Of KeyValuePair(Of String, String)).Clear
        _innerList.Clear()
    End Sub

    Public Function Contains(item As KeyValuePair(Of String, String)) As Boolean Implements ICollection(Of KeyValuePair(Of String, String)).Contains
        Return _innerList.ContainsKey(item.Key.ToLower)
    End Function

    Public Sub CopyTo(array() As KeyValuePair(Of String, String), arrayIndex As Integer) Implements ICollection(Of KeyValuePair(Of String, String)).CopyTo
        Throw New NotImplementedException
    End Sub

    Public ReadOnly Property Count As Integer Implements ICollection(Of KeyValuePair(Of String, String)).Count
        Get
            Return _innerList.Count
        End Get
    End Property

    Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of KeyValuePair(Of String, String)).IsReadOnly
        Get
            Return False
        End Get
    End Property

    Public Function Remove(item As KeyValuePair(Of String, String)) As Boolean Implements ICollection(Of KeyValuePair(Of String, String)).Remove
        If _innerList.ContainsKey(item.Key.ToLower) Then
            _innerList.Remove(item.Key.ToLower)

            Return True
        End If
        Return False
    End Function

    Public Sub Add(key As String, value As String) Implements IDictionary(Of String, String).Add
        If Not _innerList.ContainsKey(key.ToLower) Then
            _innerList.Add(key.ToLower, value)
        End If
    End Sub

    Public Function ContainsKey(key As String) As Boolean Implements IDictionary(Of String, String).ContainsKey
        Return _innerList.ContainsKey(key.ToLower)
    End Function

    Default Public Property Item(key As String) As String Implements IDictionary(Of String, String).Item
        Get
            Return _innerList(key.ToLower)
        End Get
        Set(value As String)
            If _innerList.ContainsKey(key.ToLower) Then
                _innerList(key.ToLower) = value
            Else
                _innerList.Add(key.ToLower, value)
            End If
        End Set
    End Property

    Public ReadOnly Property Keys As ICollection(Of String) Implements IDictionary(Of String, String).Keys
        Get
            Return _innerList.Keys
        End Get
    End Property

    Public Function Remove(key As String) As Boolean Implements IDictionary(Of String, String).Remove
        If _innerList.ContainsKey(key.ToLower) Then
            _innerList.Remove(key)
            Return True
        End If
        Return False
    End Function

    Public Function TryGetValue(key As String, ByRef value As String) As Boolean Implements IDictionary(Of String, String).TryGetValue
        Return _innerList.TryGetValue(key, value)
    End Function

    Public ReadOnly Property Values As ICollection(Of String) Implements IDictionary(Of String, String).Values
        Get
            Return _innerList.Values
        End Get
    End Property

    Public Function GetEnumeratorValuePair() As IEnumerator(Of KeyValuePair(Of String, String)) Implements IEnumerable(Of KeyValuePair(Of String, String)).GetEnumerator
        Return _innerList.GetEnumerator()
    End Function

    Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
        Return _innerList.GetEnumerator()
    End Function
End Class
